home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Simulation / PDP-8 Simulator / Source Code / Editor.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-13  |  17.4 KB  |  781 lines  |  [TEXT/KAHL]

  1. /*************************************************************************************
  2. *
  3. *        Editor.c    Defines types and code for generic text editor
  4. *
  5. *        Modification History:
  6. *        18/2/92 created from scratch.    
  7. *
  8. *
  9. *
  10. *************************************************************************************/
  11. #include    "EditGlobalEqu.p"
  12.  
  13. #include "Editor.proto.h"
  14.  
  15.  
  16. textEdHdl GetWEditRecord(WindowPtr theWindow);
  17. char    IsEditKind(WindowPtr theWindow);
  18.  
  19.  
  20. lineHdl NewEmptyLine(int nChars)
  21. {
  22.     /* allocates space for a new line record according to the number of chars required
  23.         sets the link pointers to NIL and length to nChars */
  24.         
  25.     lineHdl    temp;
  26.     
  27.     temp = (lineHdl) NewHandle(nChars+(sizeof(lineHdl)*2)+1);
  28.     if (temp != NIL) {
  29.         (*temp)->theLine[0] = nChars;
  30.         (*temp)->nextLine = NIL;
  31.         (*temp)->lastLine = NIL;
  32.     }
  33.     return(temp);
  34. }
  35.  
  36.  
  37. textEdHdl NewEditRecord(WindowPtr ownerWindow)
  38. {
  39.     /* creates and returns handle to new initialised edit record, with empty list. The
  40.         handle is also copied to the wRefCon field of the owner window. Normally called
  41.         for you by InitEditWindow */
  42.     
  43.     textEdHdl    temp;
  44.     Rect        tView;
  45.     GrafPtr        savePort;
  46.     
  47.     temp = (textEdHdl)NewHandle(sizeof(textRecord));
  48.     if (temp != NIL && ownerWindow != NIL) {
  49.         GetPort(&savePort);
  50.         SetPort(ownerWindow);
  51.         SetRect(&tView,0,0,256,10);
  52.         TextFont(monaco);
  53.         TextSize(9);
  54.         TextFace(0);
  55.         PenNormal();
  56.         (*temp)->listHead = NIL;
  57.         (*temp)->listTail = NIL;
  58.         (*temp)->endSelChar = 0;
  59.         (*temp)->curEdLin = 0;
  60.         (*temp)->owner = ownerWindow;
  61.         (*temp)->vScroll = NIL;
  62.         (*temp)->hScroll = NIL;
  63.         (*temp)->lineEditRec = NIL;
  64.         (*temp)->hiliteLine = 0;
  65.         (*temp)->asmFile.good = FALSE;
  66.         SetDefaultTabs(temp);
  67.         SetPort(savePort);
  68.         SetWRefCon(ownerWindow,(long)temp);
  69.     }
  70.     return(temp);
  71. }
  72.  
  73.  
  74. SetDefaultTabs(textEdHdl theText)
  75. {
  76.     /* clears tab record except for standard tab defaults */
  77.     
  78.     int        i;
  79.     
  80.     if (theText != NIL) {
  81.         for(i=0;i<10;(*theText)->tabs[i] = 4*i,i++);
  82.         
  83.     }
  84. }    
  85.     
  86.         
  87. lineHdl GetListHead(textEdHdl theEditRec)
  88. {
  89.     /* returns listHead field */
  90.     if (theEditRec != NIL)
  91.         return((*theEditRec)->listHead);
  92. }
  93.  
  94. lineHdl GetListTail(textEdHdl theEditRec)
  95. {
  96.     /* returns listTail field */
  97.     if (theEditRec != NIL)
  98.         return((*theEditRec)->listTail);
  99. }
  100.  
  101.  
  102. SetListHead(textEdHdl theEditRec,lineHdl theLink)
  103. {
  104.     /* sets listHead field */
  105.     if (theEditRec != NIL)
  106.         (*theEditRec)->listHead = theLink;
  107. }
  108.  
  109.  
  110. SetListTail(textEdHdl theEditRec,lineHdl theLink)
  111. {
  112.     /* sets listTail field */
  113.     if (theEditRec != NIL)
  114.         (*theEditRec)->listTail = theLink;
  115. }
  116.  
  117.  
  118. int    GetTabBarHeight(textEdHdl theText)
  119. {
  120.     /* gets value of tabheight field */
  121.     
  122.     if (theText != NIL)
  123.         return((*theText)->tabHeight);
  124.     else
  125.         return(0);
  126. }
  127.  
  128.  
  129. SetTabBarHeight(textEdHdl    theText,int tHeight)
  130. {
  131.     /* sets value of tabheight field (0 hides the bar) */
  132.     if (theText != NIL)
  133.         (*theText)->tabHeight = tHeight;
  134. }
  135.  
  136.  
  137. PushLink(lineHdl theLink,lineHdl *listHead,lineHdl *listTail)
  138. {
  139.     /* faster routine for inserting link as first item in list. Useful for building list
  140.         from text file as list is treated as a stack */
  141.         
  142.     lineHdl        temp;
  143.     
  144.     if (theLink != NIL) {
  145.         temp = *listHead;
  146.         (*theLink)->nextLine = temp;
  147.         (*theLink)->lastLine = NIL;
  148.         (*temp)->lastLine = theLink;
  149.         if (*listHead == NIL && *listTail == NIL)
  150.             *listTail = theLink;
  151.             
  152.         *listHead = theLink;
  153.     }    
  154. }
  155.  
  156.  
  157. ReversePushLink(lineHdl theLink,lineHdl *listHead,lineHdl *listTail)
  158. {
  159.     /* as above, but pushes link onto tail of list */
  160.     lineHdl        temp;
  161.     
  162.     if (theLink != NIL) {
  163.         temp = *listTail;
  164.         (*theLink)->lastLine = temp;
  165.         (*theLink)->nextLine = NIL;
  166.         (*temp)->nextLine = theLink;
  167.         if (*listHead == NIL && *listTail == NIL)
  168.             *listHead = theLink;
  169.             
  170.         *listTail = theLink;
  171.     }    
  172. }
  173.  
  174.  
  175. lineHdl GetLinkHandle(lineHdl listHead,int linkID)
  176. {
  177.     /* returns the handle of the link with the given ID, or NIL if no such link exists.
  178.         links are numbered starting at 1 [no link zero] */
  179.     
  180.     lineHdl        temp;
  181.     int            linkNumber = 0;
  182.     
  183.     while (listHead != NIL) {
  184.         linkNumber++;
  185.         if (linkNumber == linkID)
  186.             return(listHead);
  187.         listHead = (*listHead)->nextLine;
  188.     }
  189.     return(NIL);
  190. }
  191.  
  192.  
  193. lineHdl    BuildLine(Ptr *srcPtr,int maxChars)
  194. {
  195.     /* given a pointer to a block of text, the next line is retrieved, converted to
  196.         AAG format, copied to a new link record who's handle is returned. The line
  197.         length is also returned so that the source pointer can be updated. */
  198.     
  199.     char        newLine[256],theChar;
  200.     int            noInSect,dest;
  201.     Byte        lineLength;
  202.     lineHdl        temp;
  203.     Ptr            src;
  204.     
  205.     dest = 1;
  206.     src = *srcPtr;
  207.     lineLength = 0;
  208.     noInSect = 0;
  209.  
  210.     do {
  211.         theChar = *src;
  212.         src++;
  213.         while (theChar>=0x20 && theChar<=0xD8 && lineLength < maxChars) {
  214.             noInSect++;
  215.             newLine[dest + noInSect] = theChar;
  216.             lineLength++;
  217.             theChar = *src;
  218.             src++;
  219.         }
  220.         if (theChar == 0x09 || theChar == 0x0D || lineLength >= maxChars) {
  221.             lineLength++;
  222.             newLine[dest] = (char) noInSect;
  223.             dest += noInSect +1;    
  224.             noInSect = 0;
  225.         }
  226.     }
  227.     while (theChar != 0x0D && lineLength < maxChars);
  228.     newLine[0] = lineLength; 
  229.     temp = NewEmptyLine(lineLength);
  230.     if (temp != NIL) {
  231.         HLock((Handle) temp);
  232.         BlockMove(&newLine,&(*temp)->theLine,lineLength+1);
  233.         HUnlock((Handle) temp);
  234.     }
  235.     *srcPtr = src;    
  236.     return(temp);
  237. }
  238.  
  239.  
  240. lineHdl BuildBasicLine(Ptr *srcPtr,int maxChars)
  241. {
  242.     /* builds a line record without taking tabs into account */
  243.     char    newLine[256],theChar;
  244.     Ptr        src,dest;
  245.     int        charCount;
  246.     lineHdl    link;
  247.     
  248.     charCount = 0;
  249.     dest = &newLine[1];
  250.     src = *srcPtr;
  251.     
  252.     do {
  253.         theChar = *src;
  254.         if ((theChar >= 0x20 && theChar <= 0xD8) || theChar == 0x09) {
  255.             *dest = theChar;
  256.             dest++;  
  257.             charCount++;
  258.         }
  259.         src++;
  260.     }
  261.     while (theChar != 0x0D && charCount < maxChars);
  262.  
  263.     newLine[0] = charCount;
  264.     link = NewEmptyLine(charCount);
  265.     if (link != NIL) {
  266.         HLock((Handle) link);
  267.         BlockMove(&newLine,&(*link)->theLine,charCount+1);
  268.         HUnlock((Handle) link);
  269.     }    
  270.     *srcPtr = src;
  271.     return(link);
  272. }
  273.  
  274.  
  275. TextToList(lineHdl *listTail,lineHdl *listHead,char *theText,long textLength)
  276. {
  277.     /* major function to build a new list from a text array in memory. theText is a 
  278.         pointer to this array. listHead/Tail should initially be NIL (new list) */
  279.     
  280.     long    charCount,amountToGo;
  281.     char    *srcPtr,*oldSrcPtr;
  282.     lineHdl    newLink;
  283.     
  284.     charCount = 0;
  285.     srcPtr = theText;
  286.     oldSrcPtr = theText;
  287.     
  288.     while (charCount < textLength)    {
  289.         amountToGo = textLength - charCount;
  290.         newLink = BuildLine(&srcPtr,(amountToGo > 253)? 254:amountToGo);
  291.         if (newLink != NIL)
  292.             ReversePushLink(newLink,listHead,listTail);
  293.         charCount += (long)srcPtr - (long)oldSrcPtr;
  294.         oldSrcPtr = srcPtr;
  295.     }
  296. }
  297.  
  298.  
  299. lineHdl    GetTopLine(textEdHdl theText)
  300. {
  301.     /* returns handle to the line at the top of the window */
  302.     return(GetLinkHandle(GetListHead(theText),(*theText)->topLine));
  303. }
  304.  
  305.  
  306. lineHdl    GetBottomLine(textEdHdl theText)
  307. {
  308.     /* returns handle to the line at the bottom of the window */
  309.     return(GetLinkHandle(GetListHead(theText),(*theText)->topLine + (*theText)->linesInWindow));
  310. }
  311.  
  312.  
  313. SetHiliteLine(WindowPtr theWindow,long theLine)
  314. {
  315.     /* sets value of hiliteLine field in text record to value. 0 means no hilite */
  316.     
  317.     textEdHdl    theText;
  318.     
  319.     theText = GetWEditRecord(theWindow);
  320.     if (theText != NIL)
  321.         (*theText)->hiliteLine = theLine;
  322.     
  323. }
  324.  
  325.  
  326. CalcLinesToDraw(textEdHdl theText,Rect *theRect,lineHdl *top,lineHdl *bottom,int *drawLoc)
  327. {
  328.     /* calculates top and bottom line IDs to be drawn in the rectangle. theText must
  329.         be valid, and theRect is assumed to be in local window coordinates, which must
  330.         be current port. The handles corresponding to these lines are returned */
  331.     
  332.     int        height,p,h;
  333.     int        topID,botID,hTab;
  334.     
  335.     height = (*theText)->lineHeight;
  336.     hTab = GetTabBarHeight(theText);
  337.     p = (theRect->top - (thePort->portRect.top + hTab + 2))/height;
  338.     h = theRect->bottom - theRect->top;
  339.     *drawLoc = ((p+1) * height + hTab + 2) - (*theText)->descent;
  340.     topID = p + (*theText)->topLine;
  341.     botID = topID + (h/height);
  342.     *top = GetLinkHandle(GetListHead(theText),topID);
  343.     *bottom = GetLinkHandle(GetListHead(theText),botID);
  344. }
  345.  
  346.  
  347. int    GetMarginOffset(textEdHdl theEdRec)
  348. {
  349.     /* returns horizontal drawing origin for record */
  350.     int        margin;
  351.     
  352.     margin = ((GetCtlMin((*theEdRec)->hScroll) - 
  353.                 GetCtlValue((*theEdRec)->hScroll)) * 
  354.                  (*theEdRec)->mSpace) + 10;
  355.  
  356.     return(margin);
  357. }                        
  358.  
  359.  
  360. DrawList(WindowPtr theWindow,RgnHandle refreshRgn)
  361. {
  362.     /* scans list, drawing text into theWindow. Ports settings for lineheight etc are
  363.         used to space lines etc. If refreshRgn is not NIL, then the bounding box is
  364.         used to calculate the bare minimum to update- this improves speed & efficiency */
  365.         
  366.     int            lineHeight,margin,linePos,hLine;
  367.     lineHdl        topLine,botLine,hiliteLine;
  368.     GrafPtr        savePort;
  369.     textEdHdl    theEdRec;
  370.     Rect        refresh;
  371.     TEHandle    teText;
  372.  
  373.     if (IsEditKind(theWindow)) {
  374.         GetPort(&savePort);
  375.         SetPort(theWindow);
  376.         if (refreshRgn != NIL)
  377.             refresh = (*refreshRgn)->rgnBBox;
  378.         else
  379.             GetClipRect(theWindow,&refresh);
  380.         
  381.         theEdRec = GetWEditRecord(theWindow);
  382.         if (theEdRec != NIL) {
  383.             hLine = (*theEdRec)->hiliteLine;
  384.             if (hLine > 0)
  385.                 hiliteLine = GetLinkHandle(GetListHead(theEdRec),hLine);
  386.             CalcLinesToDraw(theEdRec,&refresh,&topLine,&botLine,&linePos);
  387.             margin = GetMarginOffset(theEdRec);
  388.             lineHeight = (*theEdRec)->lineHeight;
  389.             
  390.             while(topLine!=NIL) {
  391.                 MoveTo(margin,linePos);
  392.                 if (topLine == hiliteLine)
  393.                     ShowSelectedLine(linePos,lineHeight,(*theEdRec)->descent);
  394.                 HLock((Handle) topLine);
  395.                 /*DrawText(&(*topLine)->theLine,1,(*topLine)->theLine[0]);*/
  396.                 DrawTabText(&(*topLine)->theLine,theEdRec,margin,linePos);
  397.                 HUnlock((Handle) topLine);
  398.                 TextMode(srcOr);
  399.                 linePos += lineHeight;
  400.                 if (topLine==botLine)
  401.                     break;
  402.                     
  403.                 topLine = (*topLine)->nextLine;
  404.             }
  405.         }
  406.         SetPort(savePort);
  407.     }
  408. }
  409.  
  410.  
  411. ShowSelectedLine(int lineBase,int lineHeight,int descent)
  412. {
  413.     /* inverts given line in window */
  414.     Rect    LRect;
  415.     
  416.     /*BitClr(&HiliteMode,pHiliteBit);*/
  417.     SetRect(&LRect,0,lineBase-lineHeight+descent,640,lineBase+descent);
  418.     PaintRect(&LRect);
  419.     TextMode(patBic);
  420. }
  421.  
  422.  
  423. DrawTabText(char* lineStart,textEdHdl theText,int margin,int lineBase)
  424. {
  425.     /* given a pointer to the first location of an AAG format line in memory, this
  426.         function draws it to the screen in sections, positioning it at the tab locations
  427.         given in the tab record of theText. */
  428.         
  429.     Byte    sectionLength,tabIndex;
  430.     Byte    tLength,cCount;
  431.     int        mSpc,tabLoc,tabChar;
  432.     
  433.     cCount = 0;
  434.     tabIndex = 0;
  435.     tLength = *lineStart;
  436.     mSpc = (*theText)->mSpace;
  437.     lineStart++;                                        /* point to first section count */
  438.     do {            
  439.         sectionLength = *lineStart;                        /* get count of characters in section */
  440.  
  441.         if (sectionLength > 0)                            /* if non-zero...*/
  442.             DrawText(lineStart,1,sectionLength);        /* draw it */
  443.             
  444.         lineStart += sectionLength+1;                    /* skip to next section*/
  445.         cCount += sectionLength+1;                        /* count up how many so far */
  446.         do {
  447.             tabIndex++;                    
  448.             tabChar = (*theText)->tabs[tabIndex];        /* get next tab location */
  449.             if (tabChar != 0)
  450.                 tabLoc = margin + (tabChar * mSpc);        /* calculate pixel offset */
  451.             else
  452.                 tabLoc = thePort->pnLoc.h+mSpc;
  453.         }
  454.         while (thePort->pnLoc.h > tabLoc);
  455.         MoveTo(tabLoc,lineBase);                        /* draw from tab position */
  456.     }
  457.     while (cCount < tLength);    
  458. }
  459.  
  460.  
  461. LoadText(SFReply *theReply,WindowPtr theWindow)
  462. {
  463.     /* loads file specified in FS reply record into memory & converts it to link struct */
  464.         
  465.     Handle        temp;
  466.     OSErr        theErr;
  467.     long        byteCount;
  468.     int            pathRef;
  469.     GrafPtr        savePort;
  470.     textEdHdl    theEdRec;
  471.     
  472.     if(theReply->good && IsEditKind(theWindow)) {
  473.         theErr = FSOpen(&theReply->fName,theReply->vRefNum,&pathRef);
  474.         if (theErr == noErr) {
  475.             theErr = GetEOF(pathRef,&byteCount);
  476.             
  477.             temp = NewHandle(byteCount);
  478.             
  479.             if (temp != NIL) {
  480.                 HLock(temp);
  481.                 theErr = FSRead(pathRef,&byteCount,*temp);
  482.                 HUnlock(temp);
  483.             
  484.                 SetWTitle(theWindow,&theReply->fName);
  485.                 BuildTList(temp,theWindow);
  486.                 DisposHandle(temp);
  487.                 
  488.                 theEdRec = GetWEditRecord(theWindow);
  489.                 if (theEdRec != NIL)
  490.                     (*theEdRec)->asmFile = *theReply;
  491.             }
  492.             else
  493.                 SysBeep(1);
  494.                 
  495.             theErr = FSClose(pathRef);
  496.             GetPort(&savePort);
  497.             SetPort(theWindow);
  498.             EraseRect(&thePort->portRect);
  499.             InvalRect(&thePort->portRect);
  500.             SetPort(savePort);
  501.         }
  502.     }
  503. }
  504.  
  505.  
  506. BuildTList(Handle theText,WindowPtr theEdWindow)
  507. {
  508.     /* higher level call to TextToList using edit window parameter */
  509.     
  510.     long        tLength;
  511.     char        *cPtr;
  512.     textEdHdl    theEdRec;
  513.     lineHdl        listTail,listHead;
  514.     
  515.     if (theText != NIL && IsEditKind(theEdWindow)) {
  516.         theEdRec = GetWEditRecord(theEdWindow);
  517.         if (theEdRec != NIL) {
  518.             DisposeList(theEdRec);
  519.             listTail = GetListTail(theEdRec);
  520.             listHead = GetListHead(theEdRec);
  521.             tLength = GetHandleSize(theText);
  522.             HLock(theText);
  523.             cPtr = *theText;
  524.             TextToList(&listTail,&listHead,cPtr,tLength);
  525.             HUnlock(theText);
  526.             SetListTail(theEdRec,listTail);
  527.             SetListHead(theEdRec,listHead);
  528.             if (listHead != NIL)
  529.                 (*theEdRec)->curEdLin = 1;
  530.             InitEdDisplay(theEdWindow);
  531.         }
  532.     }
  533. }
  534.  
  535.  
  536. DisposeList(textEdHdl theTextRec)
  537. {
  538.     /* disposes of all links in theTextRec chain. This can be used prior to removing
  539.         or reinitialising the edit record. Usually called for you by a higher level
  540.         function. The head and tail fields are set to NIL at the end */
  541.         
  542.     lineHdl        temp,disp;
  543.     
  544.     if (theTextRec != NIL) {
  545.         temp = GetListHead(theTextRec);
  546.         
  547.         while (temp != NIL) {
  548.             disp = temp;
  549.             temp = (*temp)->nextLine;
  550.             DisposHandle((Handle)disp);
  551.         }
  552.         SetListHead(theTextRec,NIL);
  553.         SetListTail(theTextRec,NIL);
  554.     }
  555. }
  556.  
  557.  
  558. DisposeEdRecord(textEdHdl theTextRec)
  559. {
  560.     /* disposes of the linked list, then disposes of itself. The refcon field of the
  561.         owner window is set to NIL, any other references to the record become invalid */
  562.     
  563.     TEHandle    txt;
  564.         
  565.     if (theTextRec != NIL) {
  566.         SetWRefCon((*theTextRec)->owner,0L);
  567.         DisposeList(theTextRec);
  568.         DisposHandle((Handle) theTextRec);
  569.     }
  570. }
  571.  
  572.  
  573. int    GetLineCharCount(textEdHdl theText,int lineID)
  574. {
  575.     /* returns the number of characters in the given line. If line non-existant, returns
  576.         zero */
  577.     
  578.     lineHdl    theLink;
  579.         
  580.     if (theText != NIL) {
  581.         theLink = GetListHead(theText);
  582.         theLink = GetLinkHandle(theLink,lineID);
  583.         if (theLink != NIL)
  584.             return((*theLink)->theLine[0]);
  585.     }
  586.     return(0);
  587. }
  588.  
  589.  
  590. long    GetNumberLines(textEdHdl  theTextRec)
  591. {
  592.     /* returns the number of lines in the edit record (by counting 'em!) */
  593.     
  594.     long    t = 0;
  595.     lineHdl    temp;
  596.     
  597.     if (theTextRec != NIL) {
  598.         temp = GetListHead(theTextRec);
  599.         
  600.         for (;temp != NIL;temp = (*temp)->nextLine,t++);
  601.         
  602.     }
  603.     return(t);
  604. }
  605.  
  606.  
  607. int GetLineHeight(WindowPtr theWindow)
  608. {
  609.     /* returns lineheight for given window's grafport */
  610.  
  611.     FontInfo    theFInfo;
  612.     GrafPtr        savePort;
  613.  
  614.     GetPort(&savePort);
  615.     SetPort(theWindow);
  616.     GetFontInfo(&theFInfo);
  617.     SetPort(savePort);
  618.     return(theFInfo.ascent + theFInfo.descent + theFInfo.leading);
  619. }
  620.  
  621.  
  622. int GetDescent(WindowPtr theWindow)
  623. {
  624.     /* returns descent for given window's grafport */
  625.  
  626.     FontInfo    theFInfo;
  627.     GrafPtr        savePort;
  628.  
  629.     GetPort(&savePort);
  630.     SetPort(theWindow);
  631.     GetFontInfo(&theFInfo);
  632.     SetPort(savePort);
  633.     return(theFInfo.descent);
  634. }
  635.  
  636.  
  637. int GetMSpace(WindowPtr theWindow)
  638. {
  639.     /* returns m space of window's font */
  640.     GrafPtr        savePort;
  641.     int            w;
  642.  
  643.     GetPort(&savePort);
  644.     SetPort(theWindow);
  645.     w = CharWidth('m');
  646.     SetPort(savePort);
  647.     return(w);
  648. }    
  649.  
  650.  
  651. int  GetLinesFit(WindowPtr theWindow)
  652. {
  653.     /* calculates how many lines can fit in theWindow height and returns it */
  654.     
  655.     Rect        r;
  656.     int            wHeight,lHeight;
  657.     textEdHdl    theText;
  658.     
  659.     if (IsEditKind(theWindow)) {
  660.         theText = GetWEditRecord(theWindow);
  661.         r = theWindow->portRect;
  662.         lHeight = GetLineHeight(theWindow);
  663.         wHeight = r.bottom - r.top - GetTabBarHeight(theText) - 17 - lHeight;
  664.         return(wHeight/lHeight);
  665.     }
  666.     else
  667.         return(0);
  668. }
  669.  
  670.  
  671. int  GetHCharsFit(WindowPtr theWindow,int mSpace)
  672. {
  673.     /* calculates how many characters can fit across theWindow and returns it */
  674.     
  675.     Rect        r;
  676.     int            wWidth;
  677.     
  678.     if (IsEditKind(theWindow)) {
  679.         r = theWindow->portRect;
  680.         wWidth = r.right - r.left - 15;
  681.         return(wWidth/mSpace);
  682.     }
  683.     else
  684.         return(0);
  685. }
  686.  
  687.  
  688. InitEdDisplay(WindowPtr theWindow)
  689. {
  690.     /* call when window first opened to initialise record to show top of file, set
  691.         insertion point, etc Normally called for you after text loaded */
  692.  
  693.     textEdHdl        theText;
  694.     int                edResult;
  695.     ControlHandle    vS,hS;
  696.         
  697.     if (IsEditKind(theWindow)) {
  698.         theText = GetWEditRecord(theWindow);
  699.         GetScrollBars(theWindow,&vS,&hS);
  700.         SetCtlValue(vS,1);
  701.         if (theText != NIL) {
  702.             (*theText)->linesSelected = 0;
  703.             (*theText)->endSelChar = 0;
  704.             (*theText)->lineHeight = GetLineHeight(theWindow);
  705.             (*theText)->descent = GetDescent(theWindow);
  706.             (*theText)->mSpace = GetMSpace(theWindow);
  707.             (*theText)->tabHeight = 0;
  708.             ReCalcLineRange(theWindow);
  709.         }
  710.     }
  711. }
  712.  
  713.  
  714. long    CalcSizeNeeded(textEdHdl theText)
  715. {
  716.     /* calculates space required to hold a text file representation of the linked list structure.
  717.         This is the sum of the handle sizes, less the link pointer sizes */
  718.         
  719.     long        runTotal = 0;
  720.     long        thisOne;
  721.     lineHdl        theLink;
  722.     
  723.     if (theText != NIL) {
  724.         theLink = GetListHead(theText);
  725.         
  726.         while (theLink != NIL) {
  727.             thisOne = GetHandleSize(theLink) - (sizeof(lineHdl)*2);
  728.             runTotal += thisOne;
  729.             theLink = (*theLink)->nextLine;
  730.         }
  731.         
  732.         return(runTotal);
  733.     }
  734.     return(NIL);
  735. }
  736.  
  737.  
  738. Handle    MakeTextFile(textEdHdl theText)
  739. {
  740.     /* given a handle to a linked text structure, a text file is generated from it, and the handle to
  741.         this returned. This can then be saved as a text file on disk if required */
  742.     
  743.     long    tfSize;
  744.     Handle    txtBlock = NIL;
  745.     lineHdl    tLink;
  746.     Ptr        s1,s2;
  747.     int        sLen;
  748.         
  749.     if (theText != NIL) {
  750.         tfSize = CalcSizeNeeded(theText);
  751.         if (tfSize > 0) {
  752.             txtBlock = NewHandle(tfSize);
  753.             if (txtBlock != NIL) {
  754.                 HLock(txtBlock);
  755.                 s2 = *txtBlock;
  756.                 tLink = GetListHead(theText);
  757.                 
  758.                 while (tLink != NIL) {
  759.                     HLock((Handle) tLink);
  760.                     s1 = &(*tLink)->theLine;    
  761.                     sLen = *s1;
  762.                     s1++;
  763.                     BlockMove(s1,s2,sLen);
  764.                     HUnlock((Handle) tLink);
  765.                     s2 += sLen;
  766.                     *s2 = 0x0D;
  767.                     s2++;
  768.                     tLink = (*tLink)->nextLine;
  769.                 }
  770.                 
  771.                 HUnlock(txtBlock);
  772.             }
  773.         }
  774.     }
  775.     return(txtBlock);
  776. }
  777.  
  778.  
  779.  
  780.         
  781.